﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace uzing
{
    public class uzCTcpClientAsync
    {
        TcpClient client;
        int recvSize;
        int recvOffset;

        bool isSendable;
        bool isReceivable;

        public delegate void EndCallback(object parameter);
        EndCallback recvCallback;
        object recvParam;

        public uzCTcpClientAsync()
        {
            isReceivable = true;
            isSendable = true;
        }

        public void RegisterClient(TcpClient Client)
        {
            client = Client;
        }

        public void ConnectToServer(string IpAddress, int Port)
        {
            client = new TcpClient();
            client.Connect(IpAddress, Port);
        }

        public void BeginSend(byte[] Data, int Offset, int Size)
        {
            if (isSendable)
            {
                client.GetStream().BeginWrite(Data, Offset, Size, _endSend, Offset);
                isSendable = false;
            }
        }

        private void _endSend(IAsyncResult result)
        {
            client.GetStream().EndWrite(result);
            isSendable = true;
        }

        public void BeginReceive(byte[] Data, int Offset, int Size, EndCallback endRecvCallback, object Parameter)
        {
            if (isReceivable)
            {
                recvSize = Size;
                recvOffset = Offset;
                recvCallback = endRecvCallback;
                recvParam = Parameter;
                isReceivable = false;
                client.GetStream().BeginRead(Data, Offset, Size, _endRecv, Data);
            }
        }

        private void _endRecv(IAsyncResult result)
        {
            int acutalRecvSize = client.GetStream().EndRead(result);
            if (recvSize != acutalRecvSize)
            {
                byte[] buffer = (byte[])result.AsyncState;
                recvOffset += acutalRecvSize;
                recvSize -= acutalRecvSize;
                client.GetStream().BeginRead(buffer, recvOffset, recvSize, _endRecv, buffer);
            }
            else
            {
                isReceivable = true;
                recvCallback(recvParam);
            }
        }
    }
}
